﻿
// demoDlg.cpp: 实现文件
//

#include "pch.h"
#include "framework.h"
#include "demo.h"
#include "demoDlg.h"
#include "afxdialogex.h"
#include <atlstr.h>

using namespace std;
using namespace cv;
#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_ABOUTBOX };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CdemoDlg 对话框



CdemoDlg::CdemoDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_DEMO_DIALOG, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CdemoDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_SLIDER1, m_slider);
	DDX_Control(pDX, IDC_PROGRESS, m_progress);
}

BEGIN_MESSAGE_MAP(CdemoDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(OK, &CdemoDlg::OnBnClickedOk)
	ON_BN_CLICKED(Cancel, &CdemoDlg::OnBnClickedCancel)
	ON_BN_CLICKED(GETNAME, &CdemoDlg::OnBnClickedGetname)
	ON_NOTIFY(NM_CUSTOMDRAW, IDC_SLIDER1, &CdemoDlg::OnNMCustomdrawSlider1)
	ON_STN_CLICKED(IDC_TEXT3, &CdemoDlg::OnStnClickedText3)
END_MESSAGE_MAP()


// CdemoDlg 消息处理程序

BOOL CdemoDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != nullptr)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时，框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// 参数init
	SetDlgItemText(IDC_TEXT, _T("50")); //静态文本显示数值
	m_slider.SetRange(0, 100);                //设置范围
	m_slider.SetPos(50);                     //设置初始位置
	//进度条init
	m_progress.SetRange(0, 210);
	//pic位置
	CWnd* pWnd;
	pWnd = GetDlgItem(IDC_VIEW3); //获取控件指针，IDC_EDIT1为控件ID号
	pWnd->MoveWindow(CRect(100, 0, 420, 200)); //在窗口左上角显示一个宽100、高100的编辑控件
	

	return TRUE;  // 除非将焦点设置到控件，否则返回 TRUE
}

void CdemoDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮，则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序，
//  这将由框架自动完成。

void CdemoDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CdemoDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}
//视频播放的实现
void CdemoDlg::showviedo(string viedo_name,int id)
{
	CDC* pDC = GetDlgItem(id)->GetDC();//根据ID获得窗口指针再获取与该窗口关联的上下文指针
	HDC hdc = pDC->GetSafeHdc();                      // 获取设备上下文句柄
	CRect rect;
	// 矩形类
	GetDlgItem(id)->GetClientRect(&rect); //获取box1客户区


	CvCapture* capture = cvCreateFileCapture(viedo_name.c_str());  //读取视频
	if (capture == NULL) {
		printf("NO capture");    //读取不成功，则标识
	   //return 1;
	};
	double fps = cvGetCaptureProperty(capture, CV_CAP_PROP_FPS);   //读取视频的帧率
	int vfps = 1000 / fps;                                        //计算每帧播放的时间
	//printf("%5.1f\t%5d\n", fps, vfps);
	double frames = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_COUNT);//读取视频中有多少帧
	//printf("frames is %f\n", frames);
	//cvNamedWindow("example",CV_WINDOW_AUTOSIZE);                  //定义窗口
	IplImage* frame;

	CvvImage cimg;

	while (1) {
		frame = cvQueryFrame(capture);                          //抓取帧
		if (frame == NULL)
			break;
		cimg.CopyOf(frame, frame->nChannels);
		cimg.DrawToHDC(hdc, &rect);
		float ratio = cvGetCaptureProperty(capture, CV_CAP_PROP_POS_AVI_RATIO);     //读取该帧在视频中的相对位置
		//printf("%f\n", ratio);
		if (!frame)break;
		//cvShowImage("IDC_STATIC",frame);                          //显示
		Sleep(vfps);
	}
	ReleaseDC(pDC);
	cvReleaseCapture(&capture);
}
//视频的播放并处理
void CdemoDlg::OnBnClickedOk()
{
	showviedo(viedo_src_name,IDC_VIEW1);
	EVM(viedo_src_name, viedo_rst_name);
	
}
//图片展示实例
void CdemoDlg::showpicture(string src_img)
{
	CDC* pDC = GetDlgItem(IDC_VIEW3)->GetDC();//根据ID获得窗口指针再获取与该窗口关联的上下文指针
	HDC hdc = pDC->GetSafeHdc();                      // 获取设备上下文句柄
	CRect rect;
	// 矩形类
	GetDlgItem(IDC_VIEW3)->GetClientRect(&rect); //获取box1客户区
	CvvImage cimg;
	IplImage* src; // 定义IplImage指针变量src     
	src = cvLoadImage(src_img.c_str(), -1); //  
	cimg.CopyOf(src, src->nChannels);

	cimg.DrawToHDC(hdc, &rect);
	//输出图像
	ReleaseDC(pDC);
	cimg.Destroy();
}
//图片的展示botton
void CdemoDlg::OnBnClickedCancel()
{
	showpicture(picture_name);
	showviedo(viedo_rst_name, IDC_VIEW2);

}

//打开文件--获取viedo名
void CdemoDlg::OnBnClickedGetname()
{
	CString m_strFilePath = _T("");

	//打开图像文件，获取文件路径名
	LPCTSTR szFilter = _T("");
	CFileDialog dlgFileOpenImg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilter, NULL);
	//打开图像
	if (dlgFileOpenImg.DoModal() == IDOK)
	{
		//读取图像文件名
		m_strFilePath = dlgFileOpenImg.GetPathName();

		viedo_src_name = CT2A(m_strFilePath.GetString()); 
		string daihouzhui = viedo_src_name.substr(viedo_src_name.find_last_of("\\") + 1);
		string budaihouzhui = daihouzhui.substr(0,daihouzhui.find_last_of('.'));
		string wenjianjia = viedo_src_name.substr(0,viedo_src_name.find_last_of("\\") + 1);
		viedo_rst_name = wenjianjia + budaihouzhui + "_result.avi";
		picture_name= wenjianjia + budaihouzhui + "_result.jpg";
	}
	else
	{
		return;
	}
}

//参数的显示
void CdemoDlg::OnNMCustomdrawSlider1(NMHDR* pNMHDR, LRESULT* pResult)
{
	LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);
	// TODO: 在此添加控件通知处理程序代码
	*pResult = 0;
	int nPos = m_slider.GetPos();
	CString strText;
	strText.Format(_T("滑块%d"), nPos);
	SetDlgItemText(IDC_TEXT, strText);//实时显示滑块位置
}
//进度条的显示
void CdemoDlg::showprogress(int i,int num)
{
	CString str;
	m_progress.StepIt();
	str.Format(_T("进度%f"), float(i)/float(num));
	GetDlgItem(IDC_TEXT2)->SetWindowText(str);
}
void CdemoDlg::draw(float cost[210][256], int loc)
{
	initgraph(420, 200);
	setbkcolor(WHITE);
	cleardevice();
	for (int i = 0; i < 210; i++)
	{
		putpixel(2 * i, 200 - int(float(cost[i][loc])), BLACK);
	}
	saveimage(picture_name.c_str());
	closegraph();
}

void CdemoDlg::EVM(string src, string rst)
{
		    VideoCapture frame(src);
			int NUM = frame.get(CV_CAP_PROP_FRAME_COUNT);
			m_progress.SetRange(0, NUM);
			m_progress.SetStep(1);
		    VideoWriter writer(rst, CV_FOURCC('M', 'J', 'P', 'G'), 30, Size(512, 512));
		    Mat img, out;
		    vector<Mat_<Vec3f>>result;
		    vector<Mat_<Vec3f>>low;
		    vector<Mat_<Vec3f>>high;
		    int number = 0;
		#define level 7    
		    while (1)
		    {
		        vector<Mat_<Vec3f>>pyramid;
		        frame >> img;
		        if (img.empty())
		        {
		            break;
		        }
		        else
		        {
		            img.convertTo(img, CV_32FC3, 1.0 / 255.0f);
		            Mat imgyiq;
		            imgyiq = rgb2yiq(img);
		            Mat imgba = imgyiq.clone();
		            laplacianpyramid(imgyiq, level, pyramid);
		            if (number == 0)
		            {
		                low.assign(pyramid.begin(), pyramid.end());
		                high.assign(pyramid.begin(), pyramid.end());
		                result.assign(pyramid.begin(), pyramid.end());
		            }
		            else
		            {
		                IIR(pyramid, result, low, high);
		                returnsrc(result, out, 15, 24);
		                out = (out + imgba);
		                Mat finnal = yiq2rgb(out);
		                finnal.convertTo(finnal, CV_8UC3, 255.0);
		                writer << finnal;
		                waitKey(1);
		            }
		            number++;
					showprogress(number,NUM);
		        }
		    }
		
		
		    VideoCapture frame1(rst);
		    int flag = 0;
		    float cost[210][256];
		    while (true)
		    {
		        frame1 >> img;
		        flag++;
		        if (img.empty())
		        {
		            break;
		        }
		        if (flag > 210)
		        {
		            break;
		        }
		        for (int i = 0; i < 16; i++)
		        {
		            for (int j = 0; j < 16; j++)
		            {
		                Mat imgrio = img(Rect(i * 32, j * 32, 32, 32));
		                cost[flag - 1][j + i * 16] = count(imgrio);
		            }
		        }
		
		    }
		    int loc = find(cost);
		    draw(cost, loc);
			double array[210];
			for (int i = 0; i < 210; i++)
				array[i] = cost[i][loc];
			int peakFs[210] = { 0 };			//不知道会找到几个,故申请的稍大
			int peakFs_len = 0;
			int peakFs2[210] = { 0 };		//不知道会找到几个,故申请的稍大
			int peakFs2_len = 0;
			float T=findT(array, 210, 15, peakFs, &peakFs_len, peakFs2, &peakFs2_len);
			CString str;
			str.Format(_T("心率:%f"), T);
			GetDlgItem(IDC_TEXT3)->SetWindowText(str);
}



void CdemoDlg::OnStnClickedText3()
{
	// TODO: 在此添加控件通知处理程序代码
}
